/**
 * OSAmI: Open Source Ambient Intelligence
 * Copyright (C) 2010 LCIS - CTSYS - INPG
 * Contact: osami-general@osami-commons.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 */

package org.osami.gateway.jennic.internal;

import java.util.ArrayList;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.List;

import org.apache.felix.ipojo.ComponentInstance;
import org.apache.felix.ipojo.Factory;
import org.apache.felix.ipojo.annotations.Component;
import org.apache.felix.ipojo.annotations.Invalidate;
import org.apache.felix.ipojo.annotations.Provides;
import org.apache.felix.ipojo.annotations.Requires;
import org.apache.felix.ipojo.annotations.Validate;
import org.osami.gateway.jennic.IMessageHandler;
import org.osami.gateway.jennic.IMessageSource;
import org.osami.gateway.jennic.IPayload;
import org.osami.gateway.jennic.IPayloadParser;
import org.osami.gateway.jennic.Message;
import org.osami.gateway.jennic.PayloadParsingException;
import org.osami.gateway.jennic.internal.message.ByePayload;
import org.osami.gateway.jennic.internal.message.HelloPayload;
import org.osgi.service.device.Constants;

@Component
@Provides
public class Discovery implements IMessageHandler {

    private List<ComponentInstance> componentInstances;

    @Requires(filter = "(factory.name=org.osami.gateway.jennic.internal.JennicDevice)")
    Factory nodeFactory;

    @Requires(filter = "(type=discovery)")
    private IMessageSource source;

    @Requires
    private IPayloadParser parser;

    public Discovery() {
        this.componentInstances = new ArrayList<ComponentInstance>();
    }

    @Validate
    public void start() {
        source.registerHandler(this);
    }

    @Invalidate
    public void stop() {
        /*for (ComponentInstance instance : componentInstances) {
            instance.dispose();
        }*/
    }

    public void handle(Message message) {
        String payloadAsString = message.getPayload();
        // Need to parse payload
        IPayload payload = null;
        try {
            payload = parser.parse(payloadAsString);

            if (IPayload.Type.HELLO.equals(payload.getType())) {
                HelloPayload hello = (HelloPayload) payload;

                String nodeId = hello.getId();
                String expectedInstanceName = "org.osami.gateway.jennic.internal.JennicNode_" + nodeId;
                System.out.println("From node " + nodeId + " got 1 hello: " + hello);

                for (ComponentInstance instance : componentInstances) {
                    String instanceName = instance.getInstanceName();
                    if (instanceName.equals(expectedInstanceName)) {
                        System.out.println("Found existing JennicNode instance for " + nodeId + ", not creating one");
                        return;
                    }
                }
                System.out.println("Creating JennicNode instance for " + nodeId + ".");
                try {

                    Dictionary<String, Object> requiresFilters = new Hashtable<String, Object>();
                    requiresFilters.put("temperature", "(&(sense.type=Temp)(device.id=" + nodeId + "))");
                    requiresFilters.put("humidity", "(&(sense.type=Hydro)(device.id=" + nodeId + "))");
                    requiresFilters.put("light", "(&(sense.type=Light)(device.id=" + nodeId + "))");

                    Dictionary<String, Object> instanceConfiguration = new Hashtable<String, Object>();
                    instanceConfiguration.put(Constants.DEVICE_SERIAL, nodeId);
                    instanceConfiguration.put("instance.name", expectedInstanceName);
                    instanceConfiguration.put("requires.filters", requiresFilters);

                    // Call factory for instance creation
                    ComponentInstance ci = nodeFactory.createComponentInstance(instanceConfiguration);
                    componentInstances.add(ci);
                    System.out.println("JennicNode instance for " + nodeId + " created.");
                } catch (Throwable t){
                    t.printStackTrace();
                }
            }
            else if (IPayload.Type.BYE.equals(payload.getType())) {
                ByePayload bye = (ByePayload) payload;

                String nodeId = bye.getId();
                String expectedInstanceName = "org.osami.gateway.jennic.internal.JennicNode_" + nodeId;
                System.out.println("From node " + nodeId + " got 1 bye: " + bye);

                for (ComponentInstance instance : componentInstances) {
                    String instanceName = instance.getInstanceName();
                    if (instanceName.equals(expectedInstanceName)) {
                        System.out.println("Found existing JennicNode instance for " + nodeId + ", disposing it");
                        instance.dispose();
                        return;
                    }
                }
                System.out.println("Got 1 bye but found no matching JennicNode instance !");
            }
        } catch (PayloadParsingException e) {
            e.printStackTrace();
        }
    }
}
